package com.fang.gateway.security.service;

import com.fang.gateway.entity.po.TbNetDisUser;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Component
public class FluxReactiveAuthenticationManager implements ReactiveAuthenticationManager {

    @Resource
    private AuthorityService authorityService;

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        // 自定义认证逻辑
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        //根据用户名查询用户
        TbNetDisUser sysUser = authorityService.findUserByUsername(username);
        if (sysUser == null) {
            throw new InternalAuthenticationServiceException("用户不存在");
        }
        // 是否过期
        if (!sysUser.getNotExpired()) {
            throw new AccountExpiredException("账号已过期");
        }
        // 账号是否可用
        if (!sysUser.getEnabled()) {
            throw new DisabledException("账号已过期");
        }
        // 证书（密码）是否过期
        if (!sysUser.getCredentialsNotExpired()) {
            throw new CredentialsExpiredException("密码已过期");
        }
        // 账号是否锁定
        if (!sysUser.getAccountNotLocked()) {
            throw new LockedException("该用户已被冻结");
        }
        // 我们还要判断密码是否正确，这里我们的密码使用BCryptPasswordEncoder进行加密的
        if (!new BCryptPasswordEncoder().matches(password, sysUser.getPassword())) {
            throw new BadCredentialsException("密码不正确");
        }

        // 获取该用户所拥有的权限
        List<String> userAuthorities = authorityService.queryUserAuthorityByUserId(sysUser.getUserId());
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        // 声明用户授权

        userAuthorities.forEach(userAuthority -> {
            // GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(CommonConstants.Role.NAME_PREFIX + userRole);        // 角色需要添加前缀："ROLE_"
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(userAuthority);
            grantedAuthorities.add(grantedAuthority);
        });

        return Mono.just(new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities));
    }
}